package com.icesoft.system.safe.filter;

import com.icesoft.system.types.SystemSettingTypeDictionary;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Xss过滤器
 *
 * @author MDA
 */
@Slf4j
@RequiredArgsConstructor
@WebFilter(urlPatterns = "/*", filterName = "xssFilter")
public class XssFilter implements Filter {

	private final SystemSettingTypeDictionary systemSettingTypeDictionary;

	List<String> excludes = new ArrayList<>();

	/**
	 * 过滤器配置对象
	 */
	FilterConfig filterConfig = null;

	/**
	 * 初始化
	 */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		excludes.add("/auth/*");
		excludes.add("/common/*");
		excludes.add("/app/*");
		excludes.add("/public/*");
		excludes.add("/wechat/*");
		this.filterConfig = filterConfig;
		String tempExcludes = systemSettingTypeDictionary.getXssExcludes();
		if (StringUtils.isNotEmpty(tempExcludes)) {
			String[] url = tempExcludes.split(",");
			Collections.addAll(excludes, url);
		}
	}

	/**
	 * 拦截
	 */
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse resp = (HttpServletResponse) servletResponse;
		// 不启用或者已忽略的URL不拦截
		if (handleExcludeURL(request, resp)) {
			filterChain.doFilter(servletRequest, servletResponse);
			return;
		}
		XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper(request);
		filterChain.doFilter(xssHttpServletRequestWrapper, servletResponse);
	}

	/**
	 * 销毁
	 */
	@Override
	public void destroy() {
		this.filterConfig = null;
	}

	private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
		if (!systemSettingTypeDictionary.getXssEnable()) {
			return true;
		}
		if (excludes == null || excludes.isEmpty()) {
			excludes = new ArrayList<>();
		}
		String url = request.getServletPath();
		for (String pattern : excludes) {
			Pattern p = Pattern.compile("^" + pattern);
			Matcher m = p.matcher(url);
			if (m.find()) {
				return true;
			}
		}
		return false;
	}

}